﻿using CTP.CRM.Core.Email.Options;
using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;

namespace CTP.CRM.Core.Email.Dto
{
    public class EmailBuilder
    {
        private MimeMessage _message = null;

        private Multipart _mutipart = null;

        private readonly EmailOptions _emailOptions;

        private EmailBuilder()
        {
        }

        public EmailBuilder(EmailOptions emailOptions)
        {
            _message = new MimeMessage();
            _message.From.Add(new MailboxAddress(emailOptions.FromName, emailOptions.FromEmail));
            _emailOptions = emailOptions;
        }

        public EmailBuilder SetFromText(string fromText)
        {
            _message.From.Clear();
            _message.From.Add(new MailboxAddress(fromText, _emailOptions.FromEmail));
            return this;
        }

        public EmailBuilder SetSubject(string subject)
        {
            _message.Subject = subject;
            return this;
        }

        public EmailBuilder SetToUsers(params string[] toUsers)
        {
            foreach (string address in toUsers)
            {
                _message.To.Add(new MailboxAddress("", address));
            }

            return this;
        }

        public EmailBuilder SetToUsers(params Dictionary<string, string>[] toUsers)
        {
            foreach (Dictionary<string, string> dictionary in toUsers)
            {
                foreach (KeyValuePair<string, string> item in dictionary)
                {
                    _message.To.Add(new MailboxAddress(item.Key, item.Value));
                }
            }

            return this;
        }

        public EmailBuilder SetCcUsers(params string[] toUsers)
        {
            foreach (string address in toUsers)
            {
                _message.Cc.Add(new MailboxAddress("", address));
            }

            return this;
        }

        public EmailBuilder SetCcUsers(params Dictionary<string, string>[] toUsers)
        {
            foreach (Dictionary<string, string> dictionary in toUsers)
            {
                foreach (KeyValuePair<string, string> item in dictionary)
                {
                    _message.Cc.Add(new MailboxAddress(item.Key, item.Value));
                }
            }

            return this;
        }

        public EmailBuilder SetBody(string body)
        {
            _mutipart = _mutipart ?? new Multipart();
            _mutipart.Add(new TextPart("plain")
            {
                Text = body
            });
            return this;
        }

        public EmailBuilder SetMimePart(params Dictionary<string, Stream>[] attachments)
        {
            _mutipart = _mutipart ?? new Multipart();
            foreach (Dictionary<string, Stream> dictionary in attachments)
            {
                foreach (KeyValuePair<string, Stream> item in dictionary)
                {
                    MimePart entity = new MimePart
                    {
                        Content = new MimeContent(item.Value),
                        ContentDisposition = new ContentDisposition("attachment"),
                        ContentTransferEncoding = ContentEncoding.Base64,
                        FileName = item.Key
                    };
                    _mutipart.Add(entity);
                }
            }

            return this;
        }

        public async Task<string> SendAsync()
        {
            using SmtpClient smtp = new SmtpClient();
            await smtp.ConnectAsync(_emailOptions.SendServiceHost, _emailOptions.SendServicePort, SecureSocketOptions.SslOnConnect);
            await smtp.AuthenticateAsync(_emailOptions.FromEmail, _emailOptions.SMTPAuthorizationCode);
            _message.Body = _mutipart;
            string res = await smtp.SendAsync(_message);
            await smtp.DisconnectAsync(quit: true);
            foreach (MimeEntity streamItem in _mutipart)
            {
                streamItem.Dispose();
            }

            return res;
        }

        public string Send()
        {
            using SmtpClient smtpClient = new SmtpClient();
            smtpClient.Connect(_emailOptions.SendServiceHost, _emailOptions.SendServicePort, SecureSocketOptions.SslOnConnect);
            smtpClient.Authenticate(_emailOptions.FromEmail, _emailOptions.SMTPAuthorizationCode);
            _message.Body = _mutipart;
            string result = smtpClient.Send(_message);
            smtpClient.Disconnect(quit: true);
            foreach (MimeEntity item in _mutipart)
            {
                item.Dispose();
            }

            return result;
        }
    }
}
